package service

import (
	"strings"

	"go.uber.org/zap"
	"go-file-perception-model/internal/config"
	"go-file-perception-model/internal/logger"
)

// ChunkValidator 分块验证器
// 负责最终的分块验证和清理
type ChunkValidator struct {
	config         *config.FileIndexConfig
	chunkingConfig *ChunkingConfig
	utils         *ChunkUtils
}

// NewChunkValidator 创建分块验证器
func NewChunkValidator(cfg *config.FileIndexConfig) *ChunkValidator {
	return &ChunkValidator{
		config:         cfg,
		chunkingConfig: DefaultChunkingConfig(),
		utils:         NewChunkUtils(cfg),
	}
}

// FinalChunkValidation 最终的分块验证和清理
func (cv *ChunkValidator) FinalChunkValidation(chunks []string) []string {
	var finalResult []string
	var problematicChunks []int
	
	// 强制合并阈值：100字符（50个汉字）
	forceMinChunkSize := cv.chunkingConfig.ForceMinChunkSize
	
	// 第一步：识别问题分块（小于100字符的必须处理）
	for i, chunk := range chunks {
		chunkLen := len(strings.TrimSpace(chunk))
		if chunkLen < forceMinChunkSize {
			problematicChunks = append(problematicChunks, i)
			logger.Warn("Found problematic small chunk in final validation",
				zap.Int("index", i),
				zap.Int("length", chunkLen),
				zap.String("preview", cv.utils.GetContentPreview(chunk, 30)))
		}
	}
	
	// 第二步：强制处理问题分块
	processed := make([]bool, len(chunks))
	
	for _, problemIndex := range problematicChunks {
		if processed[problemIndex] {
			continue
		}
		
		chunk := chunks[problemIndex]
		
		// 尝试强制合并（放宽大小限制以确保合并成功）
		merged := false
		
		// 优先与后一个块合并
		if problemIndex < len(chunks)-1 && !processed[problemIndex+1] {
			nextChunk := chunks[problemIndex+1]
			// 放宽大小限制为两倍，确保能够合并
			if len(chunk)+len(nextChunk)+1 <= cv.config.MaxChunkSize*2 {
				mergedChunk := strings.TrimSpace(chunk + " " + nextChunk)
				finalResult = append(finalResult, mergedChunk)
				processed[problemIndex] = true
				processed[problemIndex+1] = true
				merged = true
				
				logger.Info("Final validation: force merged with next chunk",
					zap.Int("problem_index", problemIndex),
					zap.Int("next_index", problemIndex+1),
					zap.Int("original_length", len(chunk)),
					zap.Int("merged_length", len(mergedChunk)),
					zap.String("reason", "force_merge_below_100_chars"))
			}
		}
		
		// 如果与后一个块合并失败，尝试与前一个块合并
		if !merged && problemIndex > 0 && !processed[problemIndex-1] {
			prevChunk := chunks[problemIndex-1]
			if len(chunk)+len(prevChunk)+1 <= cv.config.MaxChunkSize*2 {
				// 需要替换最后一个元素
				if len(finalResult) > 0 {
					// 检查最后一个元素是否是前一个块
					lastElement := finalResult[len(finalResult)-1]
					if strings.TrimSpace(lastElement) == strings.TrimSpace(prevChunk) {
						finalResult = finalResult[:len(finalResult)-1] // 移除最后一个元素
					}
				}
				mergedChunk := strings.TrimSpace(prevChunk + " " + chunk)
				finalResult = append(finalResult, mergedChunk)
				processed[problemIndex] = true
				processed[problemIndex-1] = true
				merged = true
				
				logger.Info("Final validation: force merged with previous chunk",
					zap.Int("problem_index", problemIndex),
					zap.Int("prev_index", problemIndex-1),
					zap.Int("original_length", len(chunk)),
					zap.Int("merged_length", len(mergedChunk)),
					zap.String("reason", "force_merge_below_100_chars"))
			}
		}
		
		// 如果仍然无法合并，记录严重警告但仍然保留
		if !merged {
			finalResult = append(finalResult, chunk)
			processed[problemIndex] = true
			
			logger.Error("Final validation: CRITICAL - cannot merge chunk below 100 characters",
				zap.Int("index", problemIndex),
				zap.Int("length", len(chunk)),
				zap.String("content", cv.utils.GetContentPreview(chunk, 100)),
				zap.String("warning", "This chunk will still be indexed despite being too small"))
		}
	}
	
	// 第三步：添加所有未处理的正常块
	for i, chunk := range chunks {
		if !processed[i] {
			finalResult = append(finalResult, chunk)
		}
	}
	
	// 第四步：最终检查结果
	smallChunksRemaining := 0
	for _, chunk := range finalResult {
		if len(strings.TrimSpace(chunk)) < forceMinChunkSize {
			smallChunksRemaining++
		}
	}
	
	logger.Info("Final validation completed",
		zap.Int("input_chunks", len(chunks)),
		zap.Int("problematic_chunks", len(problematicChunks)),
		zap.Int("final_chunks", len(finalResult)),
		zap.Int("small_chunks_remaining", smallChunksRemaining))
	
	if smallChunksRemaining > 0 {
		logger.Warn("WARNING: Small chunks still remain after final validation",
			zap.Int("count", smallChunksRemaining))
	}
	
	return finalResult
}